<template>
  <div
    class="label_box"
    v-loading="isLoading && { text: loadingText }"
    :element-loading-text="loadingText"
  >
    <div class="toolbar_container">
      <Toolbar v-model="actionType"></Toolbar>
    </div>
    <div class="content">
      <div class="sidebar">
        <div ref="viewpointRef" class="viewpoint"></div>
        <Setting
          v-model:setting-form="settingForm"
          v-model:is-show-setting-form="isShowSettingForm"
        ></Setting>
        <Labels
          :labels="labels"
          :is-show-setting-form="isShowSettingForm"
          :is-show-labels="isShowLabels"
          @label-click="handleEditLabel"
          @toggle-labels="handleToggleLabels"
          @delete-label="handleDeleteLabel"
        ></Labels>
      </div>
      <div
        ref="containerRef"
        class="container"
        :style="{
          backgroundColor: settingForm.backgroundColor,
          backgroundImage: settingForm.backgroundImage
            ? `url(${settingForm.backgroundImage})`
            : 'none',
        }"
      ></div>
    </div>
    <EditLabelDrawer
      v-model:visible="editLabelDrawerVisible"
      v-model:point="currentPoint"
      :model-id="modelId"
      @success="handleAddLabel"
    ></EditLabelDrawer>
    <DetailDrawer
      v-model:visible="detailLabelDrawerVisible"
      v-model:edit-id="currentLabelId"
      :labels="labels"
    ></DetailDrawer>
  </div>
</template>

<script setup lang="ts">
import { ElMessageBox } from 'element-plus'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'

import { useGltfModel } from '@/hooks/useGltfModel'
import { useKeyword } from '@/hooks/useKeyboard'
import { useViewpoint } from '@/hooks/useViewpoint'
import { downloadModel } from '@/http/models'
import { delateLabelPoint, getLabelPoints } from '@/http/pointLabel'

import DetailDrawer from './components/DetailDrawer.vue'
import EditLabelDrawer from './components/EditLabelDrawer.vue'
import Labels from './components/Labels.vue'
import Setting from './components/Setting.vue'
import Toolbar from './components/Toolbar.vue'
import { EnumLabelType } from './config/config'
import { ILabel, useThree } from './hooks/useThree'

const route = useRoute()
const modelId = route.params.id as string

const { removeHotKeys, initHotKeys } = useKeyword({
  moveFunc: (keys: string, event: KeyboardEvent) => {
    if (event.type === 'keydown') {
      console.log('keydown', keys, event)
      if (actionType.value === 'addLabel') {
        actionType.value = 'move'
      }
    }
    if (event.type === 'keyup') {
      actionType.value = 'addLabel'
    }
  },
})

const actionType = ref<'addLabel' | 'move'>('addLabel')
const enabledControls = computed(() => {
  return actionType.value === 'move'
})

const isShowSettingForm = ref(true)
const settingForm = ref({
  backgroundColor: '#ffffff',
  backgroundImage: '',
})

const containerRef = ref<HTMLDivElement>()
const {
  threeModel,
  addModel,
  labels,
  controls,
  onClickModel,
  addLabel,
  removeLabel,
} = useThree(containerRef, enabledControls)

const currentPoint = ref({
  x: 0,
  y: 0,
  z: 0,
})

const handleAddLabel = (value: {
  id: string
  data: {
    point: {
      x: number
      y: number
      z: number
    }
    name: string
    type: EnumLabelType
    content: string
    file: File | null
    radius: number
    backgroundColor: string
  }
}) => {
  addLabel(
    value.id,
    value.data.point,
    value.data.name,
    value.data.type,
    value.data.content,
    value.data.backgroundColor,
    value.data.radius,
    value.data.file?.name || '',
  )
  editLabelDrawerVisible.value = false
}

onClickModel((point: { x: number; y: number; z: number }) => {
  currentPoint.value = point
  editLabelDrawerVisible.value = true
})

const loadingText = computed(() => {
  return `加载中... ${percentComplete.value}%`
})
const { loadModel, isLoading, percentComplete } = useGltfModel()

const viewpointRef = ref<HTMLDivElement>()
useViewpoint(viewpointRef, threeModel, controls)

const handleLoadModel = async () => {
  const res = await downloadModel({
    modelId,
  })
  const url = URL.createObjectURL(res.blob)
  // const url = `http://localhost:8081/元钧窑小宋自造香炉(2).glb`
  const model = await loadModel(url)

  if (model) {
    addModel(model)
  }
}

const currentLabelId = ref('')

const editLabelDrawerVisible = ref(false)

const detailLabelDrawerVisible = ref(false)
const handleEditLabel = (item: ILabel) => {
  currentLabelId.value = item.id
  detailLabelDrawerVisible.value = true
}

const isShowLabels = ref(true)
const labelsDisplay = computed(() => {
  return isShowLabels.value ? 'block' : 'none'
})
const handleToggleLabels = () => {
  isShowLabels.value = !isShowLabels.value
}

const handleDeleteLabel = async (item: ILabel) => {
  await ElMessageBox.confirm('删除该标签，是否继续?', '提示', {
    type: 'warning',
  })
  await delateLabelPoint(item.id)
  removeLabel(item.id)
}

const handleInitLabels = async () => {
  const res = await getLabelPoints(1, 1000, {
    modelId,
  })
  res.items.forEach((item) => {
    const [x, y, z] = item.dot.split(',').map(Number)
    addLabel(
      item.id,
      {
        x,
        y,
        z,
      },
      item.displayName,
      item.dotLabelType,
      item.labelText,
      item.backgroundColor,
      Number(item.radius),
      item.filePath,
    )
  })
}

onMounted(async () => {
  await handleLoadModel()
  await handleInitLabels()
  initHotKeys()
})
onBeforeUnmount(() => {
  removeHotKeys()
})
</script>

<style scoped lang="scss">
.label_box {
  width: 100vw;
  height: 100vh;
  .toolbar_container {
    height: 40px;
    width: 100%;
    background-color: #1f1f1f;
    border-bottom: 1px solid #333;
  }
  .content {
    width: 100%;
    height: calc(100vh - 40px);
    position: relative;
    .sidebar {
      width: 300px;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      background-color: #2c2c2c;
      border-right: 1px solid #333;
      overflow: hidden;
      .viewpoint {
        width: 280px;
        height: 280px;
        margin: 10px auto;
      }
    }
    .container {
      width: calc(100% - 300px);
      height: 100%;
      margin-left: 300px;
      background-repeat: no-repeat;
      background-size: cover;
      background-position: center center;
      :deep(.label) {
        display: v-bind(labelsDisplay);
      }
    }
  }
}
</style>
